package com.example.dynamicschedule.task;

import com.example.dynamicschedule.bean.CkCreditOutCompanyData;
import com.example.dynamicschedule.bean.CkCreditOutCompanyDataLog;
import com.example.dynamicschedule.bean.CkCreditOutCompanyDataRelation;
import com.example.dynamicschedule.bean.CkOutsourcingCompanyRate;
import com.example.dynamicschedule.dao.CkCreditOutCompanyDataLogMapper;
import com.example.dynamicschedule.dao.CkCreditOutCompanyDataMapper;
import com.example.dynamicschedule.dao.CkCreditOutCompanyDataRelationMapper;
import com.example.dynamicschedule.dao.CkOutsourcingCompanyRateMapper;
import com.example.dynamicschedule.utils.DateUtils;

import org.apache.commons.collections4.CollectionUtils;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

@Component
public class CreditOutcompanyRegressionRateTask {
    static Logger log = Logger.getLogger(CreditOutcompanyRegressionRateTask.class);
    @Autowired
    private DateUtils dateUtils;
    @Autowired
    private CkCreditOutCompanyDataLogMapper ckCreditOutCompanyDataLogMapper;
    @Autowired
    private CkCreditOutCompanyDataRelationMapper ckCreditOutCompanyDataRelationMapper;
    @Autowired
    private CkCreditOutCompanyDataMapper ckCreditOutCompanyDataMapper;
    @Autowired
    private CkOutsourcingCompanyRateMapper ckOutsourcingCompanyRateMapper;


    /*
     * 计算回退率
     */
    @Transactional
    public void CreditOutcompanyRegressionRateTask() throws ParseException {
        log.info("回退率计算------------------开始");
        log.info("回退率计算-------------获取上月委外数据---------------开始");
        String preBatchNumber = dateUtils.getPreBatchNumber();
        List<CkCreditOutCompanyDataLog> preCkCreditOutCompanyDataLogs = ckCreditOutCompanyDataLogMapper.selectByBatchNumberList("%" + preBatchNumber + "%");
        log.info("回退率计算-------------获取上月委外数据---------------结束");
        if (CollectionUtils.isNotEmpty(preCkCreditOutCompanyDataLogs)) {
            log.info("回退率计算-------------获取本月委外数据---------------开始");
            String batchNumber = dateUtils.getBatchNumber();
            List<CkCreditOutCompanyDataLog> ckCreditOutCompanyDataLogs = ckCreditOutCompanyDataLogMapper.selectByBatchNumberListAll("%" + batchNumber + "%");
            if (CollectionUtils.isEmpty(ckCreditOutCompanyDataLogs)) {
                ckCreditOutCompanyDataLogs = new ArrayList<>();
                List<CkCreditOutCompanyData> ckCreditOutCompanyDatas = ckCreditOutCompanyDataMapper.selectByBatchNumberListAll("%" + batchNumber + "%");
                if (CollectionUtils.isNotEmpty(ckCreditOutCompanyDatas)) {
                    for (CkCreditOutCompanyData ckCreditOutCompanyData : ckCreditOutCompanyDatas) {
                        CkCreditOutCompanyDataLog ckCreditOutCompanyDataLog = new CkCreditOutCompanyDataLog();
                        BeanUtils.copyProperties(ckCreditOutCompanyData, ckCreditOutCompanyDataLog);
                        ckCreditOutCompanyDataLogs.add(ckCreditOutCompanyDataLog);
                    }
                }
            }
            log.info("回退率计算-------------获取本月委外数据---------------结束");
            if (CollectionUtils.isNotEmpty(ckCreditOutCompanyDataLogs)) {
                log.info("回退率计算---------获取上月回退率佣金表---------开始");
                List<CkCreditOutCompanyDataRelation> ckCreditOutCompanyDataRelations = ckCreditOutCompanyDataRelationMapper.selectByBatchNumber(preBatchNumber);
                log.info("回退率计算---------获取上月回退率佣金表---------结束");
                if (CollectionUtils.isNotEmpty(ckCreditOutCompanyDataRelations)) {
                    ckCreditOutCompanyDataRelations = getCkCreditOutCompanyDataRelations(preCkCreditOutCompanyDataLogs, ckCreditOutCompanyDataLogs,
                            ckCreditOutCompanyDataRelations);
                    log.info("回退率计算---------更新回退率---------开始");
                    if (CollectionUtils.isNotEmpty(ckCreditOutCompanyDataRelations)) {
                        ckCreditOutCompanyDataRelationMapper.updateForEach(ckCreditOutCompanyDataRelations);
                    }
                    log.info("回退率计算---------更新回退率---------结束");
                } else {
                    log.info("回退率计算---------获取上月回退率佣金表为空(可能已经计算完成或无上月计算数据)---------结束");
                }
            } else {
                log.info("回退率计算---------本月委外数据为空---------结束");
            }
        } else {
            log.info("回退率计算---------上月委外数据为空---------结束");
        }
        log.info("回退率计算------------------结束");
    }

    /*
     * 计算回退率
     * @param preCkCreditOutCompanyDataLogs  上月委外案件
     * @param ckCreditOutCompanyDataLogs 本月委外按键
     * @param ckCreditOutCompanyDataRelations 回退率
     * @return*/
    private List<CkCreditOutCompanyDataRelation> getCkCreditOutCompanyDataRelations(
            List<CkCreditOutCompanyDataLog> preCkCreditOutCompanyDataLogs,
            List<CkCreditOutCompanyDataLog> ckCreditOutCompanyDataLogs,
            List<CkCreditOutCompanyDataRelation> ckCreditOutCompanyDataRelations) {
        log.info("回退率计算---------处理回退率---------开始");
        log.info("回退率计算---------处理上月案件开始---------开始");
        //更新回退率
        List<CkCreditOutCompanyDataRelation> updateCkCreditOutCompanyDataRelations = new ArrayList<>();
        //上月委外案件
        Map<String, List<CkCreditOutCompanyDataLog>> preCkCreditOutCompanyDataLogMap = new HashMap<>();
        for (CkCreditOutCompanyDataLog preCkCreditOutCompanyDataLog : preCkCreditOutCompanyDataLogs) {
            String outCompanyName = preCkCreditOutCompanyDataLog.getOutCompanyName();
            List<CkCreditOutCompanyDataLog> preCkCreditOutCompanyDataLogList = null;
            if (preCkCreditOutCompanyDataLogMap.get(outCompanyName) != null) {
                preCkCreditOutCompanyDataLogList = preCkCreditOutCompanyDataLogMap.get(outCompanyName);
            } else {
                preCkCreditOutCompanyDataLogList = new ArrayList<>();
            }
            preCkCreditOutCompanyDataLogList.add(preCkCreditOutCompanyDataLog);
            preCkCreditOutCompanyDataLogMap.put(outCompanyName, preCkCreditOutCompanyDataLogList);
        }
        preCkCreditOutCompanyDataLogs.clear();
        log.info("回退率计算---------处理上月案件开始---------结束");
        log.info("回退率计算---------处理本月案件开始---------开始");
        //本月委外按键
        Map<String, CkCreditOutCompanyDataLog> ckCreditOutCompanyDataLogMap = new HashMap<>();
        for (CkCreditOutCompanyDataLog ckCreditOutCompanyDataLog : ckCreditOutCompanyDataLogs) {
            String cardNumber = ckCreditOutCompanyDataLog.getCardNumber();
            ckCreditOutCompanyDataLogMap.put(cardNumber, ckCreditOutCompanyDataLog);
        }
        ckCreditOutCompanyDataLogs.clear();
        log.info("回退率计算---------处理本月案件开始---------结束");
        log.info("回退率计算---------回退率计算---------开始");
        //A+B除以A+B+C回退率计算公式
        for (CkCreditOutCompanyDataRelation ckCreditOutCompanyDataRelation : ckCreditOutCompanyDataRelations) {
            Integer isCalculated = ckCreditOutCompanyDataRelation.getIsCalculated();
            String outsourcingCompany = ckCreditOutCompanyDataRelation.getOutsourcingCompany();
            if (isCalculated == 2) {
                //分子
                Double b = 0.00;
                //分母
                Double a = 0.00;
                List<CkCreditOutCompanyDataLog> preCkCreditOutCompanyDataLogList = preCkCreditOutCompanyDataLogMap.get(outsourcingCompany);
                if (CollectionUtils.isNotEmpty(preCkCreditOutCompanyDataLogList)) {
                    for (CkCreditOutCompanyDataLog ckCreditOutCompanyDataLog : preCkCreditOutCompanyDataLogList) {
                        //卡号
                        String cardNumber = ckCreditOutCompanyDataLog.getCardNumber();
                        //上月期数
                        String preNumberOfOverduePeriods = ckCreditOutCompanyDataLog.getNumberOfOverduePeriods();
                        //上月逾期欠款
                        Double overdueArrears = ckCreditOutCompanyDataLog.getOverdueArrears();
                        //本月数据(若没有证明没有升期)
                        CkCreditOutCompanyDataLog preCkCreditOutCompanyDataLog = ckCreditOutCompanyDataLogMap.get(cardNumber);
                        if (preCkCreditOutCompanyDataLog != null) {
                            String numberOfOverduePeriods = preCkCreditOutCompanyDataLog.getNumberOfOverduePeriods();
                            if (Integer.valueOf(numberOfOverduePeriods) <= Integer.valueOf(preNumberOfOverduePeriods)) {
                                //未升期数据
                                b = new BigDecimal(b).add(new BigDecimal(overdueArrears)).doubleValue();
                            }
                        } else {
                            //未升期数据
                            b = new BigDecimal(b).add(new BigDecimal(overdueArrears)).doubleValue();
                        }
                        a = new BigDecimal(a).add(new BigDecimal(overdueArrears)).doubleValue();
                    }
                }
                double v = new BigDecimal(b).divide(new BigDecimal(a), 4, BigDecimal.ROUND_HALF_UP).doubleValue();
                //回退率达标率
                Set<String> outsourcingCompanySet = new HashSet<>();
                outsourcingCompanySet.add(outsourcingCompany);
                Double peopleSum=0.00;
                List<CkOutsourcingCompanyRate> ckOutsourcingCompanyRates = ckOutsourcingCompanyRateMapper.selectByOutCompanyNames(outsourcingCompanySet);
                if (CollectionUtils.isNotEmpty(ckOutsourcingCompanyRates)) {
                    CkOutsourcingCompanyRate ckOutsourcingCompanyRate = ckOutsourcingCompanyRates.get(0);
                    Double backStandard = ckOutsourcingCompanyRate.getBackStandard();
                    if (backStandard <= v) {
                        Integer peopleNumber = ckOutsourcingCompanyRate.getPeopleNumber();
                        Double peoplePrice = ckOutsourcingCompanyRate.getPeoplePrice();
                        peopleSum=new BigDecimal(peopleNumber).multiply(new BigDecimal(peoplePrice)).setScale(4,BigDecimal.ROUND_HALF_UP).doubleValue();
                    }
                }
                log.info("回退率计算---------回退率计算---------回退率为:" + v + ";委外公司为:" + outsourcingCompany);
                ckCreditOutCompanyDataRelation.setBrokerage(peopleSum);
                ckCreditOutCompanyDataRelation.setFallbackRate(v);
                ckCreditOutCompanyDataRelation.setIsCalculated(1);
                updateCkCreditOutCompanyDataRelations.add(ckCreditOutCompanyDataRelation);
            } else {
                log.info("回退率计算---------回退率计算---------已有回退率,委外公司为:" + outsourcingCompany);
            }
        }
        log.info("回退率计算---------回退率计算---------结束");
        log.info("回退率计算---------处理回退率---------结束");
        return updateCkCreditOutCompanyDataRelations;
    }
}
